import datetime
from typing import Optional, Annotated
from sqlalchemy import String, DateTime, ForeignKey, func
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.orm import Mapped, mapped_column, relationship, DeclarativeBase

str_50 = Annotated[str, 50]
str_200 = Annotated[str, 200]
int_pk = Annotated[int, mapped_column(primary_key=True)]


class Base(DeclarativeBase):
    type_annotation_map = {
            str_50: String(50)
            }


class Authors(Base):
    # Один автор - много книг
    __tablename__ = 'authors'

    id: Mapped[int_pk]
    first_name: Mapped[str_50]
    last_name: Mapped[str_50]
    books = relationship("Books", back_populates="authors", cascade="all, delete-orphan")

    def __repr__(self) -> str:
        return f"{self.first_name}, {self.last_name}"


class Books(Base):
    __tablename__ = 'books'

    id: Mapped[int_pk]
    title: Mapped[str_200]
    author_id: Mapped[int] = mapped_column(ForeignKey("authors.id", ondelete="CASCADE"))
    count: Mapped[int] = mapped_column(default=1)
    # release_date: Mapped[Date]

    # debtors: Mapped[list["Students"]] = relationship(
    #     back_populates="borrowed_books",
    #     secondary="receiving_books"
    # )
    receiving_book = relationship("ReceivingBooks", back_populates="books", cascade="all, delete-orphan")
    students = association_proxy("receiving_book", "student")

    def __repr__(self):
        return f"{self.title}, {self.author_id}, {self.count}"


class Students(Base):
    # Каждый студент может брать много книг
    __tablename__ = 'students'

    id: Mapped[int_pk]
    first_name: Mapped[str_50]
    last_name: Mapped[str_50]
    phone: Mapped[str_50]
    email: Mapped[str_50]
    average_score: Mapped[float] = mapped_column(default=1)
    scholarship: Mapped[bool] = mapped_column(default=False)
    # взятые книги студентами
    # borrowed_books: Mapped[list["Books"]] = relationship(
    #     back_populates="debtors",
    #     secondary="receiving_books"
    # )


    def __repr__(self) -> str:
        return f"{self.first_name}, {self.last_name}, {self.phone}, {self.email}"


class ReceivingBooks(Base):
    # Взятые книги в библиотеке (конкретный студент может взять много книг)
    # конкретная книга может находиться у множества студентов

    __tablename__ = 'receiving_books'

    student_id: Mapped[int] = mapped_column(
        ForeignKey("students.id", ondelete="CASCADE"),
        primary_key=True,
    )
    book_id: Mapped[int] = mapped_column(
        ForeignKey("books.id", ondelete="CASCADE"),
        primary_key=True,
    )

    date_of_issue: Mapped[datetime.datetime] = mapped_column(
        DateTime(timezone=True),
        server_default=func.now(),
        nullable=True,
        default=datetime.datetime.now,

    )
